package co.edu.udea.herbario.dao.imp;

import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import co.edu.udea.herbario.dao.EjemplarDao;
import co.edu.udea.herbario.dto.Ejemplar;
import co.edu.udea.herbario.excepcion.Excepcion;

/**
 * Esta clase contiene la implementacion de los metodos planteados en la interface 
 * EjemplarDao,los cuales son utilizados para gestionar los datos de persistencia
 * asociados a los ejemplares registrados en el sistema
 * 
 * @author Alejandro Areiza
 *
 */
public class EjemplarDaoImp extends HibernateDaoSupport implements EjemplarDao 
{
	@Override
	public List<Ejemplar> obtenerEjemplaresPorFamilia(String familia) throws Excepcion 
	{
		Session sesion = null;	//Se inicializa la variable para obtener la sesion
		List<Ejemplar> ejemplares = null;	//inicializacion de objeto tipo Lista para almacenar los
											//valores de retorno
		
		try
		{
			sesion = getSession();	//se obtiene la sesion
			//se genera la lista de todos los ejemplares de la tabla Ejemplar asociados a la familia indicada
			ejemplares = sesion.createCriteria(Ejemplar.class).add(Restrictions.like("especie.genero.familia.nombreFamilia", 
					"%" + familia +"%")).list();			
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return ejemplares;	//retorna la lista de ejemplares hallados
	}

	@Override
	public List<Ejemplar> obtenerEjemplaresPorGenero(String genero) throws Excepcion 
	{
		Session sesion = null;	//Se inicializa la variable para obtener la sesion
		List<Ejemplar> ejemplares = null;	//inicializacion de objeto tipo Lista para almacenar los
											//valores de retorno
		
		try
		{
			sesion = getSession();	//se obtiene la sesion
			//se genera la lista de todos los ejemplares de la tabla Ejemplar asociados al genero indicado
			ejemplares = sesion.createCriteria(Ejemplar.class).add(Restrictions.like("especie.genero.nombreGenero", 
					"%" + genero +"%")).list();			
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return ejemplares;	//retorna la lista de ejemplares hallados
	}

	@Override
	public List<Ejemplar> obtenerEjemplaresPorNombreCientifico(String nomCien) throws Excepcion 
	{
		Session sesion = null;	//inicializacion de objeto tipo Session
		List<Ejemplar> ejemplares = null;	//inicializacion de objeto tipo Lista para almacenar los
											//valores de retorno
		
		try
		{
			sesion = getSession();	//se obtiene la sesion
			//se genera la lista de todos los ejemplares de la tabla Ejemplar asociados al nombre cientifico 
			//indicado
			ejemplares = sesion.createCriteria(Ejemplar.class).add(Restrictions.like("nombreCientifico", 
					"%" + nomCien +"%")).list();			
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return ejemplares;	//retorna la lista de ejemplares hallados
	}	

	@Override
	public List<Ejemplar> obtenerEjemplares(String familia, String genero, String nombreCientifico, String colectorPrincipal,
			int numeroColeccion, String pais, String departamento, String municipio) throws Excepcion 
	{
		List<Ejemplar> ejemplares = null;	//inicializacion de objeto tipo Lista para almacenar los
											//valores de retorno
				
		try
		{
			//Se inicializa la variable para obtener la sesion
			Session sesion = null;
			
			//Se inicializa la variable para crear la consulta
			String consulta = "FROM Ejemplar WHERE 1=1";
			
			
			//Se valida que el valor contenido en los parametros indicados sea sea diferente de null y de vacio
			if(familia != null && !"".equals(familia))
			{
				consulta += " AND  especie.genero.famila.nombreFamilia = :nombreFamila";
			}
			
			if(genero != null && !"".equals(genero))
			{
				consulta += " AND  especie.genero.nombreGenero = :nombreGenero";
			}
			
			if(nombreCientifico != null && !"".equals(nombreCientifico))
			{
				consulta += " AND  nombreCientifico = :nombreCientifico";
			}
			
			if(colectorPrincipal != null && !"".equals(colectorPrincipal))
			{
				consulta += " AND  nombreColectorPrincipal = :colectorPrincipal";
			}
			
			if(numeroColeccion > 0)
			{
				consulta += " AND  numeroColeccion = :numeroColeccion";
			}
			
			if(pais != null && !"".equals(pais))
			{
				consulta += " AND  municipio.departamento.pais.pais = :nombrePais";
			}
			
			if(departamento != null && !"".equals(departamento))
			{
				consulta += " AND  municipio.departamento.departamento = :nombreDepartamento";
			}
			
			if(municipio != null && !"".equals(municipio))
			{
				consulta += " AND  municipio.municipio = :nombreMunicipio";
			}
			
			//Se crea el query para realizar la consulta
			//El parametro que se pasa es la cadena de la consulta 
			Query query = sesion.createQuery(consulta);			
			
			
			//Se asignan los valores de los parametros a las variables de la consulta correspondientes
			if(familia != null && !"".equals(familia))
			{
				query.setString("nombreFamilia", familia);
			}
			
			if(genero != null && !"".equals(genero))
			{
				query.setString("nombreGenero", genero);
			}
			
			if(nombreCientifico != null && !"".equals(nombreCientifico))
			{
				query.setString("nombreCientifico", nombreCientifico);
			}
			
			if(colectorPrincipal != null && !"".equals(colectorPrincipal))
			{
				query.setString("colectorPrincipal", colectorPrincipal);
			}
			
			if(numeroColeccion > 0)
			{				
				query.setInteger("numeroColeccion", numeroColeccion);			
			}
			
			if(pais != null && !"".equals(pais))
			{
				query.setString("nombrePais", pais);
			}
			
			if(departamento != null && !"".equals(departamento))
			{
				query.setString("nombreDepartamento", departamento);
			}
			
			if(municipio != null && !"".equals(municipio))
			{
				query.setString("nombreMunicipio", municipio);
			}
			
			//Se obtiene la lista de los ejemplares de acuerdo a los parametros ingresados
			ejemplares = query.list();
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return ejemplares;	//retorna la lista de ejemplares hallados
	}

	@Override
	public Ejemplar obtener(int cod) throws Excepcion 
	{
		Session sesion = null;	//Se inicializa la variable para obtener la sesion
		Ejemplar ejemplar = null;	//inicializacion de objeto tipo Ejemplar para almacenar el 
									//valor de retorno
		
		try
		{
			sesion = getSession();	//se obtiene la sesion
			//se obtiene el elemento de tipo Ejemplar asociado al codigo pasado como parametro
			ejemplar = (Ejemplar)sesion.get(Ejemplar.class, cod);			
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return ejemplar;	//retorna el elemento hallado en la tabla Ejemplar
	}

	@Override
	public int actualizar(Ejemplar ejem) throws Excepcion 
	{
		int resultado = -1;	//inicializacion de objeto tipo entero para almacenar el valor del retorno
		
		try
		{
			//actualiza la informacion del elemento ejem de tipo Ejemplar
			getHibernateTemplate().update(ejem);
			resultado = 1;	//almacena 1 como valor de retorno indicando que la operacion es exitosa
		}
		catch (HibernateException e)
		{					
			throw new Excepcion(e);		
		}
		
		return resultado;	//retorna el valor de exito o fallo de la operacion
	}

	@Override
	public int crear(Ejemplar ejem) throws Excepcion 
	{
		int resultado = -1;	//inicializacion de objeto tipo entero para almacenar el valor del retorno
		
		try
		{
			//crea el elemento ejem en la tabla Ejemplar
			getHibernateTemplate().save(ejem);		
			resultado = 1;	//almacena 1 como valor de retorno indicando que la operacion es exitosa
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);			
		}
		
		return resultado;	//retorna el valor de exito o fallo de la operacion
	}

	@Override
	public int eliminar(Ejemplar ejem) throws Excepcion 
	{
		int resultado = -1;	//inicializacion de objeto tipo entero para almacenar el valor del retorno
		
		try
		{
			//Modifica el estado del elemento de tipo Ejemplar dentro del sistema
			ejem.setDisponible(false);				//Se indica que el ejemplar esta inactivo	
			getHibernateTemplate().update(ejem);	//Se actualiza la informacion del ejemplar
			resultado = 1;	//almacena 1 como valor de retorno indicando que la operacion es exitosa
		}
		catch (HibernateException e)
		{
			throw new Excepcion(e);
		}
		
		return resultado;	//retorna el valor de exito o fallo de la operacion
	}		
}